import wx

SYMBOL_DB = {
    "510300.SH": "沪深300ETF",
    "510500.SH": "中证500ETF",
    "510050.SH": "上证50ETF",
    "510330.SH": "沪深300ETF易方达",
    "159919.SZ": "沪深300ETF嘉实",
    "159915.SZ": "创业板ETF",
}

MY_EVT_SYMBOLS_CHANGED = wx.NewEventType()
EVT_SYMBOLS_CHANGED = wx.PyEventBinder(MY_EVT_SYMBOLS_CHANGED, 1)


class SymbolListPanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent)
        self.selected_symbols = []
        self.prevent_update = False

        main_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.list_box = wx.ListBox(
            self,
            style=wx.LB_SINGLE | wx.LB_NEEDED_SB,
            size=(-1, 120)
        )
        self.list_box.Bind(wx.EVT_RIGHT_DOWN, self.on_right_click)
        self.list_box.Bind(wx.EVT_LEFT_DCLICK, self.on_double_click)
        main_sizer.Add(self.list_box, 1, wx.EXPAND | wx.RIGHT, 5)

        self.select_btn = wx.Button(self, label="选择...", size=(90, 30))
        main_sizer.Add(self.select_btn, 0, wx.ALIGN_CENTER_VERTICAL)

        self.SetSizer(main_sizer)
        self.select_btn.Bind(wx.EVT_BUTTON, self.on_select)

    def on_select(self, event):
        dlg = SymbolSelectorDialog(self, self.selected_symbols)
        if dlg.ShowModal() == wx.ID_OK:
            self.selected_symbols = dlg.get_selected()
            self.update_list()
        dlg.Destroy()

    def on_right_click(self, event):
        if self.list_box.GetCount() > 0:
            menu = wx.Menu()
            delete_item = menu.Append(wx.ID_ANY, "删除选中项")
            self.Bind(wx.EVT_MENU, lambda e: self.delete_selected(), delete_item)
            self.PopupMenu(menu)
            menu.Destroy()

    def on_double_click(self, event):
        self.delete_selected()

    def delete_selected(self):
        index = self.list_box.GetSelection()
        if index != wx.NOT_FOUND:
            del self.selected_symbols[index]
            self.update_list()

    def update_list(self):
        if self.prevent_update:
            return

        self.list_box.Clear()
        for code in self.selected_symbols:
            name = SYMBOL_DB.get(code, code)
            self.list_box.Append(f"{name} ({code})")
        self.trigger_change_event()

    def trigger_change_event(self):
        evt = wx.PyCommandEvent(MY_EVT_SYMBOLS_CHANGED, self.GetId())
        wx.PostEvent(self.GetParent(), evt)

    def get_selected(self):
        return self.selected_symbols.copy()

    def set_selected(self, symbols):
        if symbols == self.selected_symbols:
            return

        self.prevent_update = True
        self.selected_symbols = symbols.copy()
        self.update_list()
        self.prevent_update = False


class SymbolSelectorDialog(wx.Dialog):
    def __init__(self, parent, selected_symbols):
        super().__init__(parent, title="选择标的", size=(400, 500))
        self.selected = set(selected_symbols)

        main_sizer = wx.BoxSizer(wx.VERTICAL)

        self.search_ctrl = wx.SearchCtrl(self, style=wx.TE_PROCESS_ENTER)
        self.search_ctrl.SetDescriptiveText("输入代码或名称搜索...")
        main_sizer.Add(self.search_ctrl, 0, wx.EXPAND | wx.ALL, 5)

        self.list_ctrl = wx.ListCtrl(
            self,
            style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.BORDER_SUNKEN
        )
        self.list_ctrl.InsertColumn(0, "代码", width=100)
        self.list_ctrl.InsertColumn(1, "名称", width=280)
        self.list_ctrl.EnableCheckBoxes()
        main_sizer.Add(self.list_ctrl, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
        ok_btn = wx.Button(self, wx.ID_OK, "确定")
        cancel_btn = wx.Button(self, wx.ID_CANCEL, "取消")
        btn_sizer.Add(ok_btn, 0, wx.RIGHT, 10)
        btn_sizer.Add(cancel_btn, 0)
        main_sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, 10)

        self.SetSizer(main_sizer)
        self.populate_list()
        self.search_ctrl.Bind(wx.EVT_TEXT, self.on_search)
        self.list_ctrl.Bind(wx.EVT_LIST_ITEM_CHECKED, self.on_check)
        self.list_ctrl.Bind(wx.EVT_LIST_ITEM_UNCHECKED, self.on_uncheck)

    def populate_list(self, filter_str=""):
        self.list_ctrl.DeleteAllItems()
        filter_str = filter_str.upper()
        for idx, (code, name) in enumerate(SYMBOL_DB.items()):
            if filter_str in code or filter_str in name.upper():
                index = self.list_ctrl.InsertItem(idx, code)
                self.list_ctrl.SetItem(index, 1, name)
                self.list_ctrl.CheckItem(index, code in self.selected)

    def on_search(self, event):
        self.populate_list(self.search_ctrl.GetValue())

    def on_check(self, event):
        code = self.list_ctrl.GetItemText(event.GetIndex())
        self.selected.add(code)

    def on_uncheck(self, event):
        code = self.list_ctrl.GetItemText(event.GetIndex())
        self.selected.discard(code)

    def get_selected(self):
        return list(self.selected)